from bottle import route, run, template, response,request, static_file, parse_auth, default_app
import json, os, time, urllib, re
from xmlrpclib import ServerProxy
import shutil
import config

static_root = './'
@route('/hello/<name>')
def test(name):
    return template('<b>Hello {{name}}</b>!', name=name)

def return_static(filename):
    return static_file(filename, root=static_root )
# Static Routes
@route('/<filename:re:.*\.js>')
def javascripts(filename):
    return return_static(filename)

@route('/<filename:re:.*\.css>')
def stylesheets(filename):
    return return_static(filename)

@route('/<filename:re:.*\.(jpg|png|gif|ico|png)>')
def images(filename):
    return return_static(filename)

@route('/<filename:re:.*\.(eot|ttf|woff|svg)>')
def fonts(filename):
    return return_static(filename)


def convert_bytes(bytes):
    bytes = float(bytes)
    if bytes >= 1099511627776:
        terabytes = bytes / 1099511627776
        size = '%.2fTB' % terabytes
    elif bytes >= 1073741824:
        gigabytes = bytes / 1073741824
        size = '%.2fGB' % gigabytes
    elif bytes >= 1048576:
        megabytes = bytes / 1048576
        size = '%.2fMB' % megabytes
    elif bytes >= 1024:
        kilobytes = bytes / 1024
        size = '%.2fKB' % kilobytes
    else:
        size = '%.2fB' % bytes
    return size

@route('/', method='POST')
def index_POST():
    #auth = request.headers.get('Authorization')
    #if auth is not None:
    #    credentials = parse_auth(auth)
    #    print credentials
    try:
        engine = ServerProxy(config.ENGINE_XMLRPC_URL)
    except:
        pass
    response.content_type = 'application/json'
    if 'newDL' in request.POST:
        the_action ="";    
        if 'start' in request.POST:
            status = "New; Start"
            the_action = 'start'
        elif 'queue' in request.POST:
            the_action = 'queue'
            status = "New; Queue"
        elif 'pause' in request.POST:
            the_action = 'pause'
            status = "New; Stop"
        withAutoRename = request.POST.get("withAutoRename", "false")
        
        URL = request.POST.get("URL",None)
        URL = urllib.unquote(URL)
        m = re.match(r"(?P<type>[^:]+)://(?P<host>[^:/]+)(:(?P<port>\d+))?(?P<path>.*)", URL)
        mvals = m.groupdict()    
        full_dl_path = mvals['type']+'://' + mvals['host'] + urllib.quote(mvals['path'] )
        if withAutoRename == "true":
            autoRename = True
        else:
            autoRename = False
        
        if full_dl_path.endswith('/'):
            mod_url = mvals['path'].rstrip('/')
            OUT_list = mod_url.split('/')
            filename = OUT_list.pop()
        else:
            OUT_list = mvals['path'].split('/')
            filename = OUT_list.pop()
            
        
        new_job = {}
        new_job['autorename'] = autoRename
        new_job['filename'] = urllib.unquote(filename)
        dl_dir = request.get_cookie("cwd")
        if not dl_dir:
            dl_dir = config.LOCAL_DIR
        new_job['local_basedir'] = dl_dir
        new_job['status'] = status
        new_job['url'] = full_dl_path
        new_job['totalLength'] = 0 # temp
        if engine.newjob(new_job):
            returnlist = ['Added entry',urllib.unquote(filename)];
        else:
            returnlist = ['Failed to add entry',urllib.unquote(filename)];
        return json.dumps({'action_performed':the_action,'list':returnlist})
        
    elif 'up' in request.POST:
        nid = request.POST.get('up') 
        if int(nid) != 0:
            engine.upqueue(nid)
        
    elif 'down' in request.POST:
        nid = request.POST.get('down')
        engine.downqueue(nid)
    elif 'Action' in request.POST:
        returnlist = [];
        the_action ="";
        check_list_del = request.POST.getlist('delete')
        check_list_stop = request.POST.getlist('stop')
        check_list_start = request.POST.getlist('start')
        check_list_queue = request.POST.getlist('queue')
        for a_check in check_list_queue:
            if engine.queuejob(a_check):
                the_action = "queued"
            else:
                the_action = "Failed to queue"
            returnlist.append(int(a_check))
        for a_check in check_list_stop:
            
            if engine.stopjob(a_check):
                the_action="Stopped"
            else:
                the_action="Failed to stop"
            returnlist.append(int(a_check))
        if len(check_list_del) > 0:
            the_action = "Failed to delete with Data"
            if 'DelWData' in request.POST:
                if engine.deletejob(check_list_del,True):
                    the_action="Deleted"
            else: 
                if engine.deletejob(check_list_del,False):
                    the_action="Deleted"
            returnlist += check_list_del 
        for a_check in check_list_start:
            if engine.startjob(a_check):
                the_action="Started"
            else:
                the_action="Failed to start"
            returnlist.append(int(a_check))
        if 'cleanup' in request.POST:
            the_action="Cleaned Up";
            job_ids_to_cleanup = []
            for a_job in engine.getjobs():
                if a_job['status'] == 'complete':
                    job_ids_to_cleanup.append(a_job['id'])
            engine.deletejob(job_ids_to_cleanup)
            returnlist += job_ids_to_cleanup
            
        return json.dumps({'action_performed':the_action,'list':returnlist})
        #return HttpResponse(Context( {'status':'Nothing was done'} ))
        
@route('/', method='GET')
def index_GET():
    return static_file("index.html", root='site_media')
    #return 'cool, this works, hello ' + credentials[0]
@route('/dlList/')
def dlList():
    start = int(request.GET.get("start", "0"))
    limit = int(request.GET.get("limit", "2"))
    try:
        engine = ServerProxy(config.ENGINE_XMLRPC_URL)
    except:
        engine = None
    objList = []
    try:
        for a_job in engine.getjobs():
            if 'downloadSpeed' not in a_job:
                a_job['downloadSpeed'] = 0
            if 'totalLength' in a_job and 'completedLength' in a_job:
                try:
                    percent = float(a_job['completedLength']) / float(a_job['totalLength'])
                    progress = int(percent * 100)
                except:
                    progress = 0
            else:
                progress = "-"
            if 'eta' not in a_job:
                a_job['eta'] = "-"
            if 'aria2_id' not in a_job:
                a_job['aria2_id'] = -1
            if 'connections' not in a_job:
                a_job['connections'] = 0
            display_dl_speed = convert_bytes(a_job['downloadSpeed'])+'ps'
            display_totalLength = convert_bytes(a_job['totalLength'])
            a_obj = {'filename':a_job['filename'],
                            'total_size' : display_totalLength,
                            'queue_id' : a_job['queue_id'],
                            'status' : a_job['status'],
                            'dl_speed' : display_dl_speed,
                            'progress' : progress,
                            'eta' : a_job['eta'],
                            'pid' : a_job['aria2_id'],
                            'nid'  : a_job['id'],
                            'path' : a_job['local_basedir'].replace(config.LOCAL_DIR,""),
                            'connections' : a_job['connections']
                            }
            objList.append(a_obj)
    except:
        pass
    objList2 = objList
    end = start + limit
    if end > len(objList):
        end = len(objList)
    
    objList = objList[start:end]
    dataObj = { 'count' : len(objList), 'total': len(objList2),'downloads': objList }
    response.content_type = 'application/json'
    return json.dumps(dataObj)

@route('/getCWD/', method='GET')
@route('/getCWD/', method='POST')
def getCWD():
    cwd = request.get_cookie("cwd")
    if not cwd:
        cwd = config.LOCAL_DIR
    response.set_cookie("cwd", cwd, path="/")
    
    dir = cwd.replace(config.LOCAL_DIR,'')
    if len(dir) == 0:
        dir = "/"
    response.content_type = 'application/json'
    return json.dumps(dir)

@route('/dirList/', method='GET')
@route('/dirList/', method='POST')
def listDirContents():
    objList = []
    currentDir = request.GET.currentDir
    new_CWD = currentDir.lstrip('/')
    
    #Setup directory to list. Error checking here incase directory has been deleted/renamed
    dir_to_list = config.LOCAL_DIR + new_CWD
    try:    #Try and list the directory requested
        #if list is ok, save it as the working directory
        cwd = config.LOCAL_DIR + currentDir
        response.set_cookie("cwd", cwd, path="/")
    except OSError: #if there was a problem getting the contents of a directory
        #set the CWD to the web root
        cwd = config.LOCAL_DIR
        response.set_cookie("cwd", cwd, path="/")
        dir_to_list = config.LOCAL_DIR
    # encode with utf8 to ensure files/folders returned are utf8 as well
    for item in os.listdir(dir_to_list):
        full_path = os.path.join(dir_to_list, item)
        (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(full_path)
        if os.path.isdir(full_path):
            a_obj =  {'entryName':item,
                        'isDir' : "Y",
                        'size' : "-",
                        'date' : time.ctime(ctime),
                        }
            objList.append(a_obj)
        elif os.path.isfile(full_path):
            dSize = convert_bytes(size)
            a_obj =  {'entryName':item,
                        'isDir' : "N",
                        'size' : dSize,
                        'date' : time.ctime(ctime),
                        }
            objList.append(a_obj)
        

    dataObj = { 'count' : len(objList), 'total': len(objList),'dirList': objList }
    
    response.content_type = 'application/json'
    return json.dumps(dataObj)

@route('/autoDLList/', method='GET')
@route('/autoDLList/', method='POST')
def listAutoDLs():
    engine = ServerProxy(config.ENGINE_XMLRPC_URL)
    objList = []
    try:
        autodl_list = engine.getautodls()
        for entry in autodl_list:
            latest_season = entry['season_to_start']
            latest_episode = entry['episode_to_start']
            for season in entry['download_log']:
                if season > latest_season:
                    latest_season = season
            if latest_season in entry['download_log']:
                for episode in entry['download_log'][latest_season]:
                    if episode > latest_episode:
                        latest_episode = episode
            #a_obj =  {'id':entry.id,'entryName':entry.name,'season_start':entry.season_start_at,'episode_start':entry.ep_start_at}
            a_obj =  {'id':entry['id'],'proper_name':entry['proper_name'],'latest_season':latest_season,'latest_episode':latest_episode,'filenames_to_match':entry['filenames_to_match']}
            
            objList.append(a_obj)
    except:
        pass
    dataObj = { 'count' : len(objList), 'total': len(objList),'autoDLList': objList }
    response.content_type = 'application/json'
    return json.dumps(dataObj)

@route('/freespace/', method='GET')
@route('/freespace/', method='POST')
def getRemainingSpace():
    f = os.statvfs(config.LOCAL_DIR)
    space_free = f.f_bsize * f.f_bavail
    space_free=convert_bytes(space_free)
    dataObj = { 'remaining' : space_free}
    response.content_type = 'application/json'
    return json.dumps(dataObj)

@route('/enginestatus/', method='GET')
@route('/enginestatus/', method='POST')
def enginestatus():
    status = 'down'
    try:
        engine = ServerProxy(config.ENGINE_XMLRPC_URL)
        engine_status = engine.status()
        if engine_status['arai2c'] == 'online':
            status = 'up'
    except:
        status = 'down'

    response.content_type = 'application/json'
    return json.dumps(status)

@route('/autodlerstatus/', method='GET')
@route('/autodlerstatus/', method='POST')
def autodlerstatus():
    status = 'down'
    try:
        engine = ServerProxy(config.ENGINE_XMLRPC_URL)
        engine_status = engine.status()
        if engine_status['autodler'] == 'online':
            status = 'up'
    except:
        status = 'down'
        
    response.content_type = 'application/json'
    return json.dumps(status)

@route('/autoDLLog/', method='GET')
@route('/autoDLLog/', method='POST')
def autoDLLog():
    response.content_type = 'application/json'
    autoDLid = int(request.GET.get('id',-1))
    engine = ServerProxy(config.ENGINE_XMLRPC_URL)
    autodl_list = engine.getautodls()
    autodl_log = None
    for autodl_entry in autodl_list:
        if autodl_entry['id'] == autoDLid:
            autodl_log = autodl_entry['download_log']
            break
    objList = []
    if autodl_log is not None:
        for season in autodl_log:
            for episode in autodl_log[season]:
                a_obj =  {'notes':"",'ts':"",'season_num':season,'episode_num':episode}
                objList.append(a_obj)
    else:
            return json.dumps("INVALID ID:"+str(autoDLid))
    
    dataObj = { 'count' : len(objList), 'total': len(objList),'autoDLLogs': objList }
    return json.dumps(dataObj)

@route('/autodlnew/', method='GET')
@route('/autodlnew/', method='POST')
def autodlnew():
    response.content_type = 'application/json'
    #response = 'NAME:' + request.POST.get('autoDL_name','none')+'|SEASON:'+request.POST.get('autoDL_season_start','none')+'|EPISODE:'+request.POST.get('autoDL_episode_start','none')
    proper_name = request.POST.get('autoDL_proper_name','none')
    filenames_to_match = request.POST.get('autoDL_match_names','none')
    filenames_to_match = filenames_to_match.split(",")
    #getlist
    season_start = int(request.POST.get('autoDL_season_start','none'))
    episode_start = int(request.POST.get('autoDL_episode_start','none'))
        
    engine = ServerProxy(config.ENGINE_XMLRPC_URL)
    cwd = request.get_cookie("cwd")
    response = engine.newautodl(proper_name,filenames_to_match,season_start,episode_start,cwd)
    
    return json.dumps(response)
@route('/removeautodl/', method='GET')
@route('/removeautodl/', method='POST')
def removeautodl():
    response.content_type = 'application/json'
    autoDLid = int(request.POST.get('id',-1))
    try:
        engine = ServerProxy(config.ENGINE_XMLRPC_URL)
        result = engine.deleteautodl(autoDLid)
    except:
        result = "false"
    return json.dumps(result)

@route('/newdir/', method='GET')
@route('/newdir/', method='POST')
def newdir():
    dir = request.POST.get('mkDir')
    response.content_type = 'application/json'
    if dir is not None and dir !='':
        cwd = request.get_cookie("cwd")
        full_dir = cwd +dir
        try:
            os.mkdir(full_dir)
            value = 'Created DIR: '+ full_dir
        except OSError:
            value = 'Failed to create DIR: '+ full_dir
            pass
        
    else:
        value = 'Invalid DIR!'
    return json.dumps(value)

@route('/rmEntry/', method='GET')
@route('/rmEntry/', method='POST')
def removeEntry():
    response.content_type = 'application/json'
    entry = request.POST.get('rmEntry')
    entry = config.LOCAL_DIR.rstrip('/') + entry
    if entry is not None and entry !='':
        try:
            os.remove(entry)
        except OSError:
            try:
                shutil.rmtree(entry)
            except OSError:
                return json.dumps("Unable to remove entry: " + entry)
        value = 'Removed Entry: ' + entry
    else:
        value = 'Invalid Entry name'
    return json.dumps(value)

@route('/renameEntry/', method='GET')
@route('/renameEntry/', method='POST')
def renameEntry():
    response.content_type = 'application/json'
    entry = request.POST.get('renameEntry')
    newName = request.POST.get('newName')
    entry = config.LOCAL_DIR.rstrip('/') + entry
    path_list = entry.split('/')
    old_name = path_list.pop()
    path_list.append(newName)
    newName = '/'.join(path_list)
    if entry is not None and entry !='':
        try:
            os.rename(entry,newName)
        except OSError:
            return json.dumps("Unable to rename entry: " + entry +", to "+newName)
        value = 'Renamed Entry: ' + entry +", to " + newName
    else:
        value = 'Invalid Entry name'
    return json.dumps(value)

@route('/download/', method='GET')
@route('/download/', method='POST')
def download():
    path = request.GET.get('downloadpath')
    path = config.LOCAL_DIR + path
    file_list = path.split('/')
    filename = file_list.pop();
    return static_file(path, root="/" )
app = default_app()
#run(host='localhost', port=8080)
